package stockapi

import (
	"encoding/csv"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"
	"trader/utils"

	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
)

type Tencent struct {
	baseUrl   string
	referer   []string
	userAgent []string
}

func NewTencent() *Tencent {
	return &Tencent{
		baseUrl: "https://qt.gtimg.cn",
		referer: []string{"https://gu.qq.com/", "https://news.qq.com/"},
		userAgent: []string{
			"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0",
			"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
			"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36",
			"Mozilla/5.0 (Linux; Android 4.2.1; M040 Build/JOP40D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36",
			"Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/31.0.1650.18 Mobile/11B554a Safari/8536.25",
		},
	}
}

// parseSimpleStockData 解析简要接口返回的数据
// http://qt.gtimg.cn/q=s_sz000858,s_sh600188
// v_s_sz301301="51~川宁生物~301301~12.20~-0.15~-1.21~292680~35698~~272.07~GP-A-CYB"; v_s_sh601888="1~中国中免~601888~65.04~0.15~0.23~134442~87183~~1345.59~GP-A";
func (a Tencent) parseSimpleStockData(text string) (map[string]*StockQuote, error) {
	parsedData := make(map[string]*StockQuote)

	for _, data := range strings.Split(text, ";") {

		data = strings.TrimSpace(data)
		if !strings.HasPrefix(data, "v_s") {
			continue
		}

		kv := strings.Split(data, "=")
		completeCode := strings.TrimPrefix(kv[0], "v_s_")
		csvData := strings.Trim(kv[1], "\"")

		// 使用csv reader解析（分隔符为~）
		reader := csv.NewReader(strings.NewReader(csvData))
		reader.Comma = '~'
		fields, err := reader.Read()
		if err != nil {
			return nil, fmt.Errorf("CSV解析失败: " + err.Error())
		}

		// 验证字段数量
		if len(fields) < 10 {
			return nil, fmt.Errorf("数据字段不足")
		}

		// 解析数值字段
		stock := &StockQuote{
			Name: fields[1],
			Code: fields[2],
		}

		// 解析价格
		if stock.Price, err = strconv.ParseFloat(fields[3], 64); err != nil {
			return nil, fmt.Errorf("价格解析失败: " + err.Error())
		}

		// 解析涨跌
		if stock.Change, err = strconv.ParseFloat(fields[4], 64); err != nil {
			return nil, fmt.Errorf("涨跌解析失败: " + err.Error())
		}

		// 解析涨跌幅（去掉%号）
		changePercentStr := strings.TrimSpace(fields[5])
		if stock.ChangePercent, err = strconv.ParseFloat(changePercentStr, 64); err != nil {
			return nil, fmt.Errorf("涨跌幅解析失败: " + err.Error())
		}

		// 解析成交量（单位：手）
		if vol, err2 := strconv.Atoi(fields[6]); err2 == nil {
			stock.Volume = vol
		} else {
			return nil, fmt.Errorf("成交量解析失败: " + err2.Error())
		}

		// 解析成交额（单位：万）
		if stock.Turnover, err = strconv.ParseFloat(fields[7], 64); err != nil {
			return nil, fmt.Errorf("成交额解析失败: " + err.Error())
		}

		// 解析总市值（跳过空字段8）
		if stock.MarketCap, err = strconv.ParseFloat(fields[9], 64); err != nil {
			return nil, fmt.Errorf("总市值解析失败: " + err.Error())
		}

		parsedData[completeCode] = stock
	}

	return parsedData, nil
}

func (a Tencent) SimpleQuote(code string) (*StockQuote, error) {
	data, err := a.BatchSimpleQuote(code)
	if err != nil {
		return nil, err
	} else {
		for completeCode, quote := range data {
			if strings.Contains(completeCode, code) {
				return quote, nil
			}
		}

		return nil, fmt.Errorf("无法获取指定代码的数据")
	}
}

func (a Tencent) BatchSimpleQuote(codes ...string) (data map[string]*StockQuote, err error) {
	data = make(map[string]*StockQuote)
	if len(codes) == 0 {
		return
	}

	// 拼接请求地址
	simpleCodes := make([]string, 0)
	for _, code := range codes {
		completeCode, err2 := utils.CompleteStockCode(code)
		if err2 != nil {
			err = err2
			return
		}

		simpleCodes = append(simpleCodes, fmt.Sprintf("s_%s", completeCode))
	}

	url := a.baseUrl + "/q=" + strings.Join(simpleCodes, ",")

	// 发送HTTP GET请求
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Add("referer", utils.GetRandomElement(a.referer))
	req.Header.Add("user-agent", utils.GetRandomElement(a.userAgent))
	client := &http.Client{Timeout: time.Second * 5}
	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	// 将GBK响应体转换为UTF-8
	reader := transform.NewReader(resp.Body, simplifiedchinese.GBK.NewDecoder())
	content, err := io.ReadAll(reader)
	if err != nil {
		return
	}

	// 解析数据
	return a.parseSimpleStockData(string(content))
}
